Kodsnuttar och formler fr†n "Skapa dina egna virtuella utflykter" i Tekno 3/98 (med r„ttningar). --- type TPosition = record x, y, z: real; end; var star: array [1..N_STARS] of TPosition; type TVector = TPosition; TZylon = record position: TPosition; velocity: TVector; end; var zylon: array [1..MAX_ZYLONS] of TZylon; type TAttitude = record p, { Pitch } b, { Bank } h: real; { Heading } end; TShip = record position: TPosition; attitude: TAttitude; v: real; { Speed } end; var ship : TShip; function translate(const position, origin: TPosition): TPosition; begin translate.x := position.x - origin.x; translate.y := position.y - origin.y; translate.z := position.z - origin.z; end; procedure 2d_rotate(var x, y: real; const angle: real); var new_x, new_y: real; begin new_x := x * cos(angle) + y * sin(angle); new_y := y * cos(angle) - x * sin(angle); x := new_x; y := new_y; end; function 3d_rotate(const position: TPosition; const attitude: TAttitude): TPosition; var newPosition: TPosition; begin { Initialize } newPosition := position; { Heading } 2d_rotate(newPosition.y, newPosition.x, -attitude.h); { Pitch } 2d_rotate(newPosition.z, newPosition.y, attitude.p); { Bank } 2d_rotate(newPosition.z, newPosition.x, attitude.b); { Done! } 3d_rotate := newPosition; end; x' = [ cos(b)cos(h) - sin(h)sin(p)sin(b) ] x + [-cos(b)sin(h) - sin(p)cos(h)sin(b) ] y + [ cos(p)sin(b) ] z y' = [ sin(h)cos(p) ] x + [ cos(p)cos(h) ] y + [ sin(p) ] z; z' = [-cos(h)sin(b) - sin(h)sin(p)cos(b) ] x + [ sin(h)sin(b) - sin(p)cos(h)cos(b) ] y + [ cos(p)cos(b) ] z const PIXELS_PER_METER = 800 / 0.30; const VIEWER_DISTANCE = 0.50; { Meters } var mid_u, mid_v: integer; mid_u := window.width div 2; mid_v := window.height div 2; with position do begin { Projection from transformed coordinates to screen } u := mid_u + trunc((PIXELS_PER_METER * VIEWER_DISTANCE) * (x / y)); v := mid_v - trunc((PIXELS_PER_METER * VIEWER_DISTANCE) * (z / y)); end; const COLLISION_DISTANCE = 10; { Meters } function collided(const position: TPosition): boolean; { Must be called with translated position! } begin with position do collided := (x * x + y * y + z * z < COLLISION_DISTANCE * COLLISION_DISTANCE); end; const ZYLON_SIZE = 10; { Meters } function scale_factor(const y: real): real; { Must be called with Zylon's transformed y coordinate! } begin scale_factor := (PIXELS_PER_METER * VIEWER_DISTANCE) * (ZYLON_SIZE / y) end; const SPRITE_SIZE = 128; { Pixels } type TSprite = array [0..SPRITE_SIZE - 1, 0..SPRITE_SIZE - 1] of byte; procedure rescale(const source: TSprite; var destination: TSprite; const scale_factor: real); { If scale_factor < 1.0, destination must be blank } begin from_i := 0; to_i := 0; repeat from_j := 0; to_j := 0; repeat destination[to_i, to_j] := source[from_i, from_j]; from_j := trunc(to_j * scale_factor); to_j := to_j + 1; until ((from_j >= SPRITE_SIZE) or (to_j >= SPRITE_SIZE)); from_i := trunc(to_i * scale_factor); to_i := to_i + 1; until ((from_i >= SPRITE_SIZE) or (to_i >= SPRITE_SIZE)); end;